#include <string>
#include "ClsExample.h"
#include <unistd.h>
#include "RandUtils.h"

bool humanReady = false;
bool humanProcessed = false;

bool manReady = false;
bool manProcessed = false;
std::vector<std::shared_ptr<Human>> humans;
std::vector<std::shared_ptr<Man>> mans;
std::mutex mx;
std::condition_variable cv;

bool compareS2L(const std::shared_ptr<Human> &data1, const std::shared_ptr<Human> &data2)
{
    return data1->getAge() < data2->getAge();
}

bool compareL2S(const std::shared_ptr<Human> &data1, const std::shared_ptr<Human> &data2)
{
    return data1->getAge() > data2->getAge();
}

void printValue(std::shared_ptr<Human> human)
{
    printf("%s:%d human age = {%d} name = {%s} heigth = {%d}\n", __FUNCTION__, __LINE__, human->getAge(), human->getName().c_str(), human->getHeigth());
}

uint8_t outputHuman()
{
    printf("输出原始值：\n");
    // for (std::shared_ptr<Human> human : humans)
    // {
    //     printf("%s:%d human age = {%d} name = {%s} heigth = {%d}\n", __FUNCTION__, __LINE__, human->getAge(), human->getName().c_str(), human->getHeigth());
    // }
    for (size_t i = 0; i < humans.size(); i++)
    {
        auto human = humans[i];
        printf("%s:%d human age = {%d} name = {%s} heigth = {%d}\n", __FUNCTION__, __LINE__, human->getAge(), human->getName().c_str(), human->getHeigth());
    }

    printf("从小到大排序：\n");
    // sort(humans.begin(), humans.end(), compareS2L);
    sortS2L(humans);
    std::for_each(humans.begin(), humans.end(), printValue);
    printf("从大到小排序：\n");
    sortL2S(humans);
    // sort(humans.begin(), humans.end(), compareL2S);
    // std::for_each(humans.begin(), humans.end(), printValue);

    for (size_t i = 0; i < humans.size(); i++)
    {
        auto human = humans[i];
        printValue(human);
    }
    return 1;
}

uint8_t outpuMan()
{
    printf("输出原始值：\n");
    for (std::shared_ptr<Man> man : mans)
    {
        printf("%s:%d       man age = {%d} name = {%s} heigth = {%d} weigth = {%d} sex = {%d}\n", __FUNCTION__, __LINE__, man->getAge(), man->getName().c_str(), man->getHeigth(), man->getWeigth(), man->getSex());
    }
    return 1;
}

void Human::setName(std::string name)
{
    Human::name = name;
}

uint8_t setupHumanData(size_t count)
{
    srand((unsigned)time(NULL));
    for (size_t i = 0; i < count; i++)
    {
        std::shared_ptr<Human> human = std::make_shared<Human>();
        human->setAge(randAge());
        human->setHeigth(randHeigth());
        human->setName("张三" + std::to_string(i));
        humans.push_back(human);
    }
    return 1;
}

uint8_t setupManData(size_t count)
{
    srand((unsigned)time(NULL));
    for (size_t i = 0; i < count; i++)
    {
        std::shared_ptr<Man> man = std::make_shared<Man>(randAge(), randHeigth(), "man" + std::to_string(i), 1);
        mans.push_back(man);
    }
    return 1;
}

uint8_t randAge()
{
    return randAction(AGE_MAX, AGE_MIN);
}

uint8_t randHeigth()
{
    return randAction(HEIGTH_MAX, HEIGTH_MIN);
}

uint8_t doWorkHuman(size_t count)
{
    printf("human thread : waiting ...\n");
    std::unique_lock<std::mutex> lock(mx);

    cv.wait(lock, []
            { return humanReady; }); //waiting humanReady with true

    printf("human thread : action setting up data ...\n");
    sleep(1);
    setupHumanData(count);
    printf("human thread : processed\n");
    humanProcessed = true;
    lock.unlock();
    cv.notify_one();
    return 1;
}

uint8_t doWorkMan(size_t count)
{
    printf("  man thread : waiting ...\n");
    std::unique_lock<std::mutex> lock(mx);

    cv.wait(lock, []
            { return manReady; }); //waiting humanReady with true
    printf("  man thread : action setting up data ...\n");
    sleep(1);
    setupManData(count);

    printf("  man thread : processed\n");
    manProcessed = true;
    lock.unlock();
    cv.notify_one();
    return 1;
}

void createHumanThread()
{
    pthread_t pt;
    int error = 0;
    error = pthread_create(&pt, NULL, HumanWorkThread, (void *)5);
    if (error)
    {
        printf("创建Human线程失败\n");
    }
}

void createManThread()
{
    pthread_t pt;
    int error = 0;
    error = pthread_create(&pt, NULL, ManWorkThread, (void *)5);
    if (error)
    {
        printf("创建Man线程失败\n");
    }
}

int main(int argc, char const *argv[])
{
    createManThread();
    createHumanThread();
    //main thread ready
    {
        std::lock_guard<std::mutex> lock(mx);
        printf(" main thread : preparing\n");
        sleep(1);
        manReady = true;
        humanReady = true;
        printf(" main thread : ready\n");
        // cv.notify_one();//
        cv.notify_all(); //通知多个
    }
    //waiting man processed
    {
        std::unique_lock<std::mutex> lock(mx);
        cv.wait(lock, []
                { return manProcessed; });
        printf(" main thread : from man preparing\n");
        sleep(1);
        humanReady = true;
        printf(" main thread : ready\n");
        cv.notify_one();
    }
    //waiting human processed
    {
        std::unique_lock<std::mutex> lock(mx);
        cv.wait(lock, []
                { return humanProcessed; });
        printf(" main thread : from human preparing\n");
        sleep(1);
        printf("all task confirm\n");
    }
    { //输出
        outputHuman();
    }
    { //输出
        outpuMan();
    }
    Human human1;
    Human human2();
    Man man1(1, 1, "张三", 1);
    Man man2;//在cpp中默认为实例化,调用空构造函数. 定义了构造函数后,编译器不会自动生成空构造函数
    Man man3();//这种写法编译认为是变量声明
    man1.setAge(1);
    man2.setAge(1);
    man3.setAge(1);

    return 0;
}
//g++ ClsExample.cpp RandUtils.cpp SortUtils.cpp -o task -lpthread & ./client
